package com.xxx.springboot.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.xxx.springboot.annotation.NotRepeatSubmit;
import com.xxx.springboot.pojo.token.TokenInfo;
import com.xxx.springboot.util.ApiUtil;
import com.xxx.springboot.util.JsonUtil;
import com.xxx.springboot.util.MD5Util;
import com.xxx.springboot.util.RedisUtil;

/**
 * @NotRepeatSubmit 注解拦截器
 */
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
	
   /**
    * 
    * @param request
    * @param response
    * @param handler 访问的目标方法
    * @return
    * @throws Exception
    */
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       String token = request.getHeader("token");
       String timestamp = request.getHeader("timestamp");
       String nonce = request.getHeader("nonce");
       String sign = request.getHeader("sign");

       // 获取注解里的不允许重复提交的间隔时间
       NotRepeatSubmit notRepeatSubmit = ApiUtil.getNotRepeatSubmit(handler);
       long expireTime = notRepeatSubmit == null ? 5 * 60 * 1000 : notRepeatSubmit.value(); // 默认间隔5秒

       // 2. 判断请求时间间隔是否超过阈值
       long reqeustInterval = System.currentTimeMillis() - Long.valueOf(timestamp);
       if(reqeustInterval > 60*1000) {
    	   System.out.println("timeout");
    	   return false;
       }

       // 3. 校验Token是否存在
       String value = RedisUtil.get(token);
       TokenInfo tokenInfo = JsonUtil.decodeJson(value, TokenInfo.class);

       // 4. 校验签名(将所有的参数加进来，防止别人篡改参数) 所有参数看参数名升续排序拼接成url
       // 请求参数 + token + timestamp + nonce
       String signString = ApiUtil.concatSignString(request) + tokenInfo.getAppInfo().getKey() + token + timestamp + nonce;
       String signature = MD5Util.MD5_32(signString);
       boolean flag = signature.equals(sign);
       if(!flag) {
    	   System.out.println("invalid request");
    	   return false;
       }

       // 5. 拒绝重复调用(第一次访问时存储，过期时间和请求超时时间保持一致), 只有标注不允许重复提交注解的才会校验
       if (notRepeatSubmit != null) {
           boolean exists = RedisUtil.hasKey(sign);
           if(exists) {
        	   RedisUtil.set(sign, "1", expireTime/1000);
           }
       }

       return super.preHandle(request, response, handler);
   }
   
}
